package com.baikeyang.app.controller;

import com.alibaba.fastjson.JSON;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.channels.FileChannel;
import java.util.*;

/**
 * Created by lenovo on 2019/5/17.
 */
@Controller(value = "fileController")
public class FileController {


    String uploadPath;
    private static final ResourceBundle bundle = ResourceBundle.getBundle( "config/config" );

    /**
     * 分片上传
     * @param multipartFile
     * @param tempFileName 临时文件名
     * @param realName 文件真实名
     * @param chunk 分割块数
     * @param chunks 总分割数
     * @param request
     * @param response
     */
    @RequestMapping(value = "uploadDemo", method = RequestMethod.POST)
    @ResponseBody
    public String uploadFileDemo (@RequestParam("file") MultipartFile multipartFile,
                                @RequestParam("name") String tempFileName,
                                @RequestParam(value = "realName") String realName,
                                Integer chunk, Integer chunks, HttpServletRequest request, HttpServletResponse response) {
        String reuslt = "";
        response.setCharacterEncoding( "UTF-8" );
        String newFileName = null; /* 最后合并后的新文件名 */
        BufferedOutputStream outputStream	= null;

        try {
            // 上传目录：如果上传目录不存在，则创建该目录
            uploadPath = request.getServletContext().getRealPath( bundle.getString( "system.file.upload.directory" ) );
            File up = new File( uploadPath );
            if ( !up.exists() ) {
                up.mkdir();
            }

            // 创建文件目录
            File dir = new File( uploadPath+File.separator+tempFileName+File.separator);
            if(!dir.exists()){
                dir.mkdirs();
            }

            String filePath = uploadPath+File.separator+tempFileName+File.separator+chunk;//合并文件必须要按照顺序合并，所以不能重命名
            multipartFile.transferTo(new File(filePath));

            newFileName = UUID.randomUUID().toString().replace( "-", "" )
                    .concat( "." )
                    .concat( FilenameUtils.getExtension( tempFileName ) );

            if(chunk == chunks-1){// 开始合并文件
                System.out.println("可以合并了");
                mergeUpload(uploadPath, tempFileName, realName);
            }

            Map<String, Object> m = new HashMap<String, Object>();
            m.put( "status", true );
            m.put( "fileUrl", bundle.getString( "system.file.upload.directory" ) + "/" + newFileName );
            reuslt = JSON.toJSONString( m );
        } catch (IOException e) {
            e.printStackTrace();
        }
        return reuslt;
    }


    @RequestMapping(value="uploadFile", method= RequestMethod.POST)
    public void uploadFile(HttpServletRequest request, HttpServletResponse response   ) throws IOException {

        response.setCharacterEncoding( "UTF-8" );
        Integer chunk = null; /* 分割块数 */
        Integer chunks = null; /* 总分割数 */
        String tempFileName = null; /* 临时文件名 */
        String newFileName = null; /* 最后合并后的新文件名 */
        BufferedOutputStream outputStream	= null;



		/* System.out.println(FileUtils.getTempDirectoryPath()); */
        uploadPath = request.getServletContext().getRealPath( bundle.getString( "system.file.upload.directory" ) );
        File up = new File( uploadPath );
        if ( !up.exists() )
        {
            up.mkdir();
        }

        if ( ServletFileUpload.isMultipartContent( request ) )
        {
            try {
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold( 1024 );
				/* factory.setRepository(new File(repositoryPath));// 设置临时目录 */
                ServletFileUpload upload = new ServletFileUpload( factory );
                upload.setHeaderEncoding( "UTF-8" );
				/* upload.setSizeMax(5 * 1024 * 1024);// 设置附件最大大小，超过这个大小上传会不成功 */
                List<FileItem> items = upload.parseRequest( request );
                for ( FileItem item : items )
                {
                    if ( item.isFormField() ) /* 是文本域 */
                    {
                        if ( item.getFieldName().equals( "name" ) )
                        {
                            tempFileName = item.getString();
							/* System.out.println("临时文件名：" + tempFileName); */
                        } else if ( item.getFieldName().equals( "chunk" ) )
                        {
                            chunk = Integer.parseInt( item.getString() );
							/* System.out.println("当前文件块：" + (chunk + 1)); */
                        } else if ( item.getFieldName().equals( "chunks" ) )
                        {
                            chunks = Integer.parseInt( item.getString() );
							/* System.out.println("文件总分块：" + chunks); */
                        }
                    } else { /* 如果是文件类型 */
                        if ( tempFileName != null )
                        {
                            String chunkName = tempFileName;
                            if ( chunk != null )
                            {
                                chunkName = chunk + "_" + tempFileName;
                            }
                            File savedFile = new File( uploadPath, chunkName );
                            item.write( savedFile );
                        }
                    }
                }

                newFileName = UUID.randomUUID().toString().replace( "-", "" )
                        .concat( "." )
                        .concat( FilenameUtils.getExtension( tempFileName ) );
                if ( chunk != null && chunk + 1 == chunks )
                {
                    outputStream = new BufferedOutputStream(
                            new FileOutputStream( new File( uploadPath, newFileName ) ) );
					/* 遍历文件合并 */
                    for ( int i = 0; i < chunks; i++ )
                    {
                        File tempFile = new File( uploadPath, i + "_" + tempFileName );
                        byte[] bytes = FileUtils.readFileToByteArray( tempFile );
                        outputStream.write( bytes );
                        outputStream.flush();
                        tempFile.delete();
                    }
                    outputStream.flush();
                }
                Map<String, Object> m = new HashMap<String, Object>();
                m.put( "status", true );
                m.put( "fileUrl", bundle.getString( "uploadPath" ) + "/"
                        + newFileName );
                response.getWriter().write( JSON.toJSONString( m ) );
            } catch ( FileUploadException e ) {
                e.printStackTrace();
                Map<String, Object> m = new HashMap<String, Object>();
                m.put( "status", false );
                response.getWriter().write( JSON.toJSONString( m ) );
            } catch ( Exception e ) {
                e.printStackTrace();
                Map<String, Object> m = new HashMap<String, Object>();
                m.put( "status", false );
                response.getWriter().write( JSON.toJSONString( m ) );
            } finally {
                try {
                    if ( outputStream != null )
                        outputStream.close();
                } catch ( IOException e ) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ResourceBundle bundle = ResourceBundle.getBundle( "config/config" );
        System.out.println(bundle.getString("system.file.upload.directory"));

        try {
            String path = "F:\\Develop\\YouthPro\\web-app\\target\\web-app\\uploadImg";
            String resourcesDirectory = "o_1db1pkas3h331ut1plg1trv102b7.JPG";
            String targetFile = "1db1pkas3h331ut1plg1trv102b7.JPG";
            mergeUpload(path, resourcesDirectory, targetFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 合并上传目录文件
     * @param path 目录位置
     * @param resourcesDirectory 源目录
     * @param target 目标文件
     */
    public static void mergeUpload(String path, String resourcesDirectory,String target) throws IOException {

        // 1、先找到源目录下的所有被合并文件
        File f = new File( path + File.separator + resourcesDirectory);
        File[] fileArray = f.listFiles(new FileFilter() {
            // 排除目录，只要文件
            public boolean accept(File pathname) {
                if (pathname.isDirectory()) {
                    return false;
                }
                return true;
            }
        });
        if(null != fileArray && fileArray.length > 0){
            // 转成集合，便于排序
            List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
            // 按照分片的顺序排
            Collections.sort(fileList, new Comparator<File>() {
                public int compare(File o1, File o2) {
                    if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
                        return -1;
                    }
                    return 1;
                }
            });

            // 2、创建合并文件
            File file = new File(path + File.separator + target);
            file.createNewFile();
            // 获取输出流
            FileChannel outChannel  = new FileOutputStream(file).getChannel();

            // 3、开始合并
            FileChannel inChannel;
            for (File tmp : fileList) {
                inChannel = new FileInputStream(tmp).getChannel();
                inChannel.transferTo(0, inChannel.size(), outChannel);
                inChannel.close();
                // 删除分片
                tmp.delete();
            }
            if (outChannel != null) {
                // 清除临时文件
                deleteFile(f);
                // 关闭流
                outChannel.close();
            }
        }else{
            System.out.println("没有需要合并的文件");
        }

    }

    /**
     * 递归删除文件夹
     * @param file
     * @return
     */
    public static boolean deleteFile(File file) {
        if(file==null||!file.exists()){

            return true;
        }
        if (file.isDirectory()) {
            String[] children = file.list();//递归删除目录中的子目录下
            for (int i=0; i<children.length; i++) {
                boolean success = deleteFile(new File(file, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return file.delete();
    }

}
